package com.inoneone.youba.mcht.controller;

import com.inoneone.toolkit.enums.BooleanType;
import com.inoneone.toolkit.enums.CardStatus;
import com.inoneone.toolkit.enums.MchtStatus;
import com.inoneone.toolkit.exception.AssertUtil;
import com.inoneone.toolkit.exception.BusinessRuntimeException;
import com.inoneone.toolkit.exception.RegExp;
import com.inoneone.youba.mcht.dao.po.*;
import com.inoneone.youba.mcht.dto.BaseRsp;
import com.inoneone.youba.mcht.dto.req.AddSerialReq;
import com.inoneone.youba.mcht.dto.req.BeginOrderReq;
import com.inoneone.youba.mcht.dto.req.EndOrderReq;
import com.inoneone.youba.mcht.dto.req.GetOrderReq;
import com.inoneone.youba.mcht.dto.rsp.BeginOrderRsp;
import com.inoneone.youba.mcht.dto.rsp.GetLeastVersionRsp;
import com.inoneone.youba.mcht.dto.rsp.GetOrderRsp;
import com.inoneone.youba.mcht.dto.rsp.GetTimeRsp;
import com.inoneone.youba.mcht.enums.Constants;
import com.inoneone.youba.mcht.enums.ErrorCode;
import com.inoneone.youba.mcht.service.CardApi;
import com.inoneone.youba.mcht.service.HotUpdateApi;
import com.inoneone.youba.mcht.service.MerchantApi;
import com.inoneone.youba.mcht.service.OrderApi;
import com.inoneone.youba.mcht.util.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.UnknownFormatConversionException;


@RestController
@RequestMapping(value = "/IoT", method = {RequestMethod.GET})
public class IoTController {
    Logger logger = LoggerFactory.getLogger(this.getClass());
    @Autowired
    private MerchantApi merchantApi;

    @Autowired
    private CardApi cardApi;

    @Autowired
    private OrderApi orderApi;

    @Autowired
    private HotUpdateApi hotUpdateApi;

    /**
     * Description: 开始加油</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/getOrder")
    @ResponseBody
    public Object getOrder(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        //获取加密数据
        String content = request.getParameter("content");

        logger.info("收到getOrder请求");
        logger.info("boxId = "+ boxId);
        logger.info("content = "+ content);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        //解密
        String jsonData = DesUtil.decrypt(content, tanker.getSecretKey());
        GetOrderReq getOrderReq = StringUtil.jsonParse(jsonData, GetOrderReq.class);

        //解密参数检查
        AssertUtil.isMatch(getOrderReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.isMatch(getOrderReq.getClientTime(), RegExp.TIME, ErrorCode.DATE_TIME);
        AssertUtil.isMatch(getOrderReq.getSalt(), RegExp.SALT, ErrorCode.ERR_SALT);
        AssertUtil.isMatch(getOrderReq.getSecret(), RegExp.SECRET, ErrorCode.ERR_SECRET);

        //校验ic卡是否属于该商户
        Card card = cardApi.queryCard(getOrderReq.getCardId(), tanker.getMchId());

        //身份校验
        String identitySecret = DesUtil.encrypt(getOrderReq.getSalt(), card.getSecretKey());
        if (!identitySecret.equals(getOrderReq.getSecret())) {
            throw new BusinessRuntimeException(ErrorCode.IDENTITY_BAD);
        }

        //校验卡状态
        if (card.getStatus() == CardStatus.FREEZEN.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.CARD_FREEZE);
        }

        //校验余额是否为0
        if (card.getBalance().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessRuntimeException(ErrorCode.CARD_ZERO);
        }

        //获取商户信息
        Merchant merchant = merchantApi.queryMchById(tanker.getMchId());

        //校验商户状态
        if (merchant.getStatus() == MchtStatus.FORBIDDEN.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.MCH_BAD_STATUS);

        }

        //获取业务锁
        BusinessLock businessLock = orderApi.getBusinessLock(getOrderReq.getCardId());

        String orderId = "";
        //是否锁定
        if (businessLock != null && businessLock.getIsLocked() == BooleanType.YES.getCode()) {

            orderId = String.valueOf(businessLock.getOrderId());
        }
        else
        {
            //生成新订单
            FuelOrder fuelOrder = orderApi.createOrder(card, tanker);

            //业务锁
            orderApi.lock(fuelOrder.getCardId(), fuelOrder);

            orderId = String.valueOf(fuelOrder.getOrderId());
        }

        GetOrderRsp getOrderRsp = new GetOrderRsp();
        getOrderRsp.setOrderId(orderId);
        getOrderRsp.setBalance(card.getBalance().setScale(2).toString());
        getOrderRsp.setPrice(tanker.getPrice().setScale(2).toString());
        getOrderRsp.setServerTime(DateUtil.formatDate(new Date(), Constants.IOT_DATE_FORMAT));

        //返回数据加密
        String enResult = DesUtil.encrypt(StringUtil.jsonFormat(getOrderRsp), tanker.getSecretKey());

        logger.debug("返回数据：");
        logger.debug(enResult);

        //返回
        BaseRsp baseRsp = new BaseRsp(enResult);
        return baseRsp;
    }

    /**
     * Description: 开始加油</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/beginOrder")
    @ResponseBody
    @Deprecated
    public Object beginOrder(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        //获取加密数据
        String content = request.getParameter("content");

        logger.info("收到beginOrder请求");
        logger.info("boxId = "+ boxId);
        logger.info("content = "+ content);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        //解密
        String jsonData = DesUtil.decrypt(content, tanker.getSecretKey());
        BeginOrderReq beginOrderReq = StringUtil.jsonParse(jsonData, BeginOrderReq.class);

        //解密参数检查
        AssertUtil.isMatch(beginOrderReq.getCardId(), RegExp.CARD_NO, ErrorCode.CARD);
        AssertUtil.isMatch(beginOrderReq.getClientTime(), RegExp.TIME, ErrorCode.DATE_TIME);
        AssertUtil.isMatch(beginOrderReq.getSalt(), RegExp.SALT, ErrorCode.ERR_SALT);
        AssertUtil.isMatch(beginOrderReq.getSecret(), RegExp.SECRET, ErrorCode.ERR_SECRET);

        //校验ic卡是否属于该商户
        Card card = cardApi.queryCard(beginOrderReq.getCardId(), tanker.getMchId());

        //身份校验
        String identitySecret = DesUtil.encrypt(beginOrderReq.getSalt(), card.getSecretKey());
        if (!identitySecret.equals(beginOrderReq.getSecret())) {
            throw new BusinessRuntimeException(ErrorCode.IDENTITY_BAD);
        }


        //校验卡状态
        if (card.getStatus() == CardStatus.FREEZEN.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.CARD_FREEZE);
        }

        //校验余额是否为0
        if (card.getBalance().compareTo(BigDecimal.ZERO) <= 0) {
            throw new BusinessRuntimeException(ErrorCode.CARD_ZERO);
        }

        //获取商户信息
        Merchant merchant = merchantApi.queryMchById(tanker.getMchId());

        //校验商户状态
        if (merchant.getStatus() == MchtStatus.FORBIDDEN.getCode()) {
            throw new BusinessRuntimeException(ErrorCode.MCH_BAD_STATUS);

        }

        String isPrev = "0";
        if(!CommonUtil.isNullOrEmpty(beginOrderReq.getPrevOrderId()))
        {
            //查询上次订单
            FuelOrder lastFuelOrder = orderApi.queryOrder(Long.valueOf(beginOrderReq.getPrevOrderId()));

            //获取业务锁
            BusinessLock businessLock = orderApi.getBusinessLock(lastFuelOrder.getCardId());

            //业务锁判断
            if (businessLock != null && businessLock.getIsLocked() == BooleanType.YES.getCode()) {

                //上次订单参数检查
                AssertUtil.isMatch(beginOrderReq.getPrevOrderId(), RegExp.ORDER_ID, ErrorCode.ORDER_NO);
                AssertUtil.isMatch(beginOrderReq.getPrevAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
                AssertUtil.isMatch(beginOrderReq.getPrevCharge(), RegExp.AMOUNT_YUAN, ErrorCode.ERR_FUEL);
                AssertUtil.isMatch(beginOrderReq.getPrevEndTime(), RegExp.TIME, ErrorCode.DATE_TIME);


                if (!businessLock.getTankId().equals(boxId)) {
                    throw new BusinessRuntimeException(ErrorCode.BUSINESS_LOCK_WRONG, "原加油机编号为[" + businessLock.getTankId() + "]");
                }

                Long prevOrderId = Long.valueOf(beginOrderReq.getPrevOrderId());
                if (!businessLock.getOrderId().equals(prevOrderId)) {
                    throw new BusinessRuntimeException(ErrorCode.BUSINESS_LOCK_ORDER, "原加油机编号为[" + businessLock.getTankId() + "]");

                }

                isPrev = "1";

                //完结上次订单
                EndOrderReq endOrderReq = new EndOrderReq();
                endOrderReq.setOrderId(beginOrderReq.getPrevOrderId());
                endOrderReq.setEndTime(beginOrderReq.getPrevEndTime());
                endOrderReq.setCharge(beginOrderReq.getPrevCharge());
                endOrderReq.setAmount(beginOrderReq.getPrevAmount());
                orderApi.complateLastOrder(endOrderReq, merchant, card, tanker);

                //业务锁解锁
                orderApi.unlock(beginOrderReq.getCardId());
            } else {
                //nothing
            }
        }

        //生成新订单
        FuelOrder fuelOrder = orderApi.createOrder(card, tanker);

        //业务锁
        orderApi.lock(fuelOrder.getCardId(), fuelOrder);

        //获取最新余额
        Card cardlatest = cardApi.queryCard(fuelOrder.getCardId(), fuelOrder.getMchId());

        BeginOrderRsp beginOrderRsp = new BeginOrderRsp();
        beginOrderRsp.setOrderId(String.valueOf(fuelOrder.getOrderId()));
        beginOrderRsp.setBalance(cardlatest.getBalance().setScale(2).toString());
        beginOrderRsp.setIsPrev(isPrev);
        beginOrderRsp.setPrice(tanker.getPrice().setScale(2).toString());
        beginOrderRsp.setServerTime(DateUtil.formatDate(new Date(), Constants.IOT_DATE_FORMAT));

        //返回数据加密
        String enResult = DesUtil.encrypt(StringUtil.jsonFormat(beginOrderRsp), tanker.getSecretKey());

        logger.debug("返回数据：");
        logger.debug(enResult);

        //返回
        BaseRsp baseRsp = new BaseRsp(enResult);
        return baseRsp;
    }

    /**
     * Description: 结束加油</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/endOrder")
    @ResponseBody
    public Object endOrder(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        //获取加密数据
        String content = request.getParameter("content");

        logger.info("收到endOrder请求");
        logger.info("boxId = "+ boxId);
        logger.info("content = "+ content);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        //解密
        String jsonData = DesUtil.decrypt(content, tanker.getSecretKey());
        EndOrderReq endOrderReq = StringUtil.jsonParse(jsonData, EndOrderReq.class);

        //解密参数检查
        AssertUtil.isMatch(endOrderReq.getAmount(), RegExp.AMOUNT_YUAN_ZERO, ErrorCode.AMOUNT);
        AssertUtil.isMatch(endOrderReq.getCharge(), RegExp.AMOUNT_YUAN_ZERO, ErrorCode.ERR_FUEL);
        AssertUtil.isMatch(endOrderReq.getEndTime(), RegExp.TIME, ErrorCode.DATE_TIME);
        AssertUtil.isMatch(endOrderReq.getOrderId(), RegExp.ORDER_ID, ErrorCode.ORDER_NO);


        //查询订单
        FuelOrder fuelOrder = orderApi.queryOrder(Long.valueOf(endOrderReq.getOrderId()));

        //获取业务锁
        BusinessLock businessLock = orderApi.getBusinessLock(fuelOrder.getCardId());

        if (!businessLock.getTankId().equals(boxId)) {
            throw new BusinessRuntimeException(ErrorCode.BUSINESS_LOCK_WRONG, "原加油机编号为[" + businessLock.getTankId() + "]");
        }

        if (!businessLock.getOrderId().equals(Long.valueOf(endOrderReq.getOrderId()))) {
            throw new BusinessRuntimeException(ErrorCode.BUSINESS_LOCK_ORDER, "原加油机编号为[" + businessLock.getTankId() + "]");

        }

        if(businessLock.getIsLocked() == BooleanType.YES.getCode())
        {

            //获取商户信息
            Merchant merchant = merchantApi.queryMchById(tanker.getMchId());

            //查询ic卡
            Card card = cardApi.queryCard(fuelOrder.getCardId(), fuelOrder.getMchId());

            //完结订单
            orderApi.complateLastOrder(endOrderReq, merchant, card, tanker);

            //业务锁解锁
            orderApi.unlock(fuelOrder.getCardId());
        }
        else
        {
            //幂等校验 TODO

        }

        //返回
        return new BaseRsp();
    }

    /**
     * Description: 上传加油流水信息</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/addSerial")
    @ResponseBody
    public Object addSerial(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        //获取加密数据
        String content = request.getParameter("content");

        logger.info("收到addSerial请求");
        logger.info("boxId = "+ boxId);
        logger.info("content = "+ content);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        //解密
        String jsonData = DesUtil.decrypt(content, tanker.getSecretKey());
        AddSerialReq addSerialReq = StringUtil.jsonParse(jsonData, AddSerialReq.class);

        //解密参数校验
        AssertUtil.isMatch(addSerialReq.getOrderId(), RegExp.ORDER_ID, ErrorCode.ORDER_NO);
        AssertUtil.isMatch(addSerialReq.getAmount(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        AssertUtil.isMatch(addSerialReq.getBalance(), RegExp.AMOUNT_YUAN, ErrorCode.AMOUNT);
        AssertUtil.isMatch(addSerialReq.getCharge(), RegExp.AMOUNT_YUAN, ErrorCode.ERR_FUEL);
        AssertUtil.isMatch(addSerialReq.getSerialNo(), RegExp.SERIAL_NO, ErrorCode.SERIAL_NO);
        AssertUtil.isMatch(addSerialReq.getPrice(), RegExp.AMOUNT_YUAN, ErrorCode.ERR_PRICE);
        AssertUtil.isMatch(addSerialReq.getSerialTime(), RegExp.TIME, ErrorCode.DATE_TIME);


        //查询订单
        FuelOrder fuelOrder = orderApi.queryOrder(Long.valueOf(addSerialReq.getOrderId()));

        //增加流水
        orderApi.addOrderFlow(fuelOrder, addSerialReq);

        //返回
        return new BaseRsp();
    }

    /**
     * Description: 获取服务器时间</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/getTime")
    @ResponseBody
    public Object getTime(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        logger.info("收到getTime请求");
        logger.info("boxId = "+ boxId);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        GetTimeRsp getTimeRsp = new GetTimeRsp();
        getTimeRsp.setServerTime(DateUtil.formatDate(new Date(), Constants.IOT_DATE_FORMAT));

        //返回数据加密
        String enResult = DesUtil.encrypt(StringUtil.jsonFormat(getTimeRsp), tanker.getSecretKey());

        //返回
        BaseRsp baseRsp = new BaseRsp(enResult);
        return baseRsp;
    }


    /**
     * Description: 结束加油</br>
     * Date: 2017-07-04 14:44:18</br>
     *
     * @param
     * @return
     * @author 姬远玄
     * @since JDK 1.7
     */
    @GetMapping(value = "/getLeastVersion")
    @ResponseBody
    public Object getLeastVersion(HttpServletRequest request) {

        //盒子id（加油机id）
        String boxId = request.getParameter("boxId");

        logger.info("收到getLeastVersion请求");
        logger.info("boxId = "+ boxId);

        //查询盒子密钥
        Tanker tanker = merchantApi.queryTanker(boxId);
        if (tanker == null) {
            throw new BusinessRuntimeException(ErrorCode.TANKER_NOT_EXIST);
        }

        //查询最新数据
        GetLeastVersionRsp getLeastVersionRsp = hotUpdateApi.getLeastVersion();

        //数据加密
        String enResult = DesUtil.encrypt(StringUtil.jsonFormat(getLeastVersionRsp), tanker.getSecretKey());

        //返回
        return new BaseRsp(enResult);
    }
}
